#include <arpa/inet.h>
#include <openssl/cmac.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <pcap.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include "psp.h"

int recv_size;
int main()
{
    int s, client_address_size;
    struct sockaddr_in client, server;
    char *cfg_file = DEFAULT_DECRYPT_CFG_FILE;
    struct pkt_context pkt_ctx;
    unsigned char *in_pkt;

    pkt_ctx.max_pkt_octets = ETH_JUMBO_MAX_OCTETS;
    pkt_ctx.out_pkt = NULL;
    pkt_ctx.scratch_buf = NULL;

    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket()");
        exit(1);
    }

    server.sin_family      = AF_INET;  
    server.sin_port        = htons(1000);         
    server.sin_addr.s_addr = INADDR_ANY;

    if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        perror("bind()");
        exit(2);
    }

    /* read psp config file */
    if (get_psp_cfg(cfg_file, &pkt_ctx, PSP_MODE_DECRYPT) != SUCCESS_RC) goto err_exit;

    pkt_ctx.in_pkt = calloc(1, pkt_ctx.max_pkt_octets);
    if (pkt_ctx.in_pkt == NULL) {
        fprintf(stderr, "calloc() failed\n");
        goto err_exit;
    }

    /* allocate packet buffers */
    pkt_ctx.out_pkt = calloc(1, pkt_ctx.max_pkt_octets);
    if (pkt_ctx.out_pkt == NULL) {
        fprintf(stderr, "calloc() failed\n");
        goto err_exit;
    }

    pkt_ctx.scratch_buf = calloc(1, pkt_ctx.max_pkt_octets);
    if (pkt_ctx.scratch_buf == NULL) {
        fprintf(stderr, "calloc() failed\n");
        goto err_exit;
    }

    in_pkt = pkt_ctx.in_pkt;

    int count = 0;
    while(1) {

        client_address_size = sizeof(client);

        if((recv_size = recvfrom(s, in_pkt, pkt_ctx.max_pkt_octets, 0, (struct sockaddr *) &client,
                                 &client_address_size)) < 0)
        {
            perror("recvfrom()");
            exit(4);
        }
        count++;
        printf("\n count:%d recv size:%d address:%s port:%d packet:\n",count, recv_size,inet_ntoa(client.sin_addr), ntohs(client.sin_port));
        // for(int i = 0; i < recv_size; i++) {
        //     printf("%02x ", in_pkt[i]);
        // }
        fflush(stdout);
        pkt_ctx.psp_payload_len = recv_size;

        parse_packet(&pkt_ctx);

        if (sendto(s, in_pkt, recv_size, 0,
                   (struct sockaddr *)&client, sizeof(client)) < 0)
        {
            perror("sendto()");
            exit(2);
        }
    
    }
err_exit:
    free(pkt_ctx.in_pkt);
    free(pkt_ctx.out_pkt);
    free(pkt_ctx.scratch_buf);
    close(s);
    return 0;
}
